import Vue from 'vue'
// 导入路由插件
import VueRouter from 'vue-router'
// 导入放在 views文件夹里面 login.vue 子组件
import login from '../views/login/login.vue'
import home from '../views/home/home.vue'
import movie from '../views/movie/movie.vue'
import my from '../views/my/my.vue'
import question from '../views/question/question.vue'
// 导入404页面
import notfound from '../views/notfound/notfound.vue'
// 6月29号--------6月29号6月29号--------------------------6月29号
import article from '../views/article/article.vue'
// 导入Search页面 home页面的搜索
import search from '../views/search/search.vue'
// 6月30号--------------------6月30号-------------
import result from '../views/result/result.vue'
import student from '../views/student/student.vue'

// 6月24号 新建页面 edit.vue-------------6月24号----
import edit from '../views/edit/edit.vue'
// 6月24号--------6月24号6月24号--------------------------
// 导入utils里面的token.js 工具函数
import { getToken, removeToken } from '../utils/token'
// Vant 官网的轻提示插件
import { Toast } from 'vant'
// 导入 api里面的 my.js(用户信息的)
import { getUserInfo } from '../api/my.js'
// 导入仓库对象
import store from '..//store/index'

// 注册路由
Vue.use(VueRouter)

// 配置路由的规则
// -----------6月21号----------6月21号------------------
// 路由元信息 额外的给路由添加信息,可以通过`路由元信息`来实现
// 可以在不影响逻辑的情况下加一些状态进去 (在App.vue获取到这里的数据进行判断)
// meta:{showTab: true} 直接在路由配置的时候，给每个路由添加一个自定义的meta对象，
// 在meta对象中可以设置一些状态，来进行一些操作。用它来做登录校验再合适不过了
const routes = [
  {
    // 路径
    path: '/login',
    // 组件
    component: login
  },
  {
    path: '/home',
    component: home,
    // 路由元信息
    meta: {
      showTab: true
    }
  },
  {
    // 文章详情页 需要携带id 和设置name: 'article',6月29号-----------6月29号-----------
    // path: '/detail/:id' 参数一般都是id,其他nam component不变
    path: '/article/:id',
    name: 'article',
    component: article
  },
  {
    path: '/search',
    name: 'search',
    component: search,
    // 路由元信息
    meta: {
      showTab: true
    }
  },
  {
    // 6月30号--------------------6月30号-------------
    path: '/result',
    name: 'result',
    component: result
  },
  {
    // 6月30号--------------------6月30号-------------
    path: '/student',
    name: 'student',
    component: student,
    meta: {
      // 判断需要登陆的页面
      needLogin: true
    }
  },
  {
    path: '/movie',
    component: movie,
    // 路由元信息
    meta: {
      showTab: true
    }
  },
  {
    path: '/my',
    component: my,
    meta: {
      showTab: true,
      // 6月24号----------------6月24号----------------
      // 标记需要登陆的页面(如果其他页面需要判断登陆  直接用即可-需要登陆才能访问的页面)
      // 他的值是true,说明需要登陆,那就需要在 导航守卫里 面去做判断了(如果有token就登陆,如果没有就提示用户去登陆页面)
      needLogin: true
    }
  },
  {
    // 6月24号 新建页面 edit.vue-------------6月24号------------
    path: '/edit',
    component: edit,
    // 路由元信息
    meta: {
      // 其他页面需要判断登陆 直接用即可 needLogin它已经做了路由守卫做好了判断
      needLogin: true
    }
  },
  {
    path: '/question',
    component: question,
    meta: {
      showTab: true
    }
  },
  // 404页面的规则
  {
    path: '/notfound',
    component: notfound
  },
  //  输入 / 去home页面
  {
    path: '/',
    redirect: '/home'
    // 下面这样的写法两个地址都可以配备到home页面,
    // 但是在当前页面需要配置meta:{showTab: true} 才能显示到底部页面 所有不建议使用
    // component: home
  },
  // 找不到去 notfound 404页面
  {
    path: '*',
    redirect: '/notfound'
  }
]

// 6月24号-----------------6月24号------------------
// 处理路由切换的 Promise 的reject错误 (加在实例化 VueRouter 的上面)
// 吞掉 没有处理的 promise的错误 (这是一段固定代码)
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location, onResolve, onReject) {
  if (onResolve || onReject) {
    // 执行之后 阻断后续代码
    return originalPush.call(this, location, onResolve, onReject)
  }
  return originalPush.call(this, location).catch(err => err)
}

// 实例化路由对象
const router = new VueRouter({
  routes
})
//    6月23号在最下面----------------------------6月23号----------
// 6月24号 注册导航守卫-----------------6月24号---------------------
router.beforeEach((to, from, next) => {
  // to里面是可以拿到路由元想信息meta里面的数据 needLogin: true showTab: true
  // (所以通够过判断当前页面是否有这个 needLogin值)
  // console.log('to:', to)
  if (to.meta.needLogin === undefined) {
    // 等于undefined说明不需要登陆, 阻断后续代码执行)
    return next()
  }
  // 需要登陆 因为return next()已经阻断了下面这些代码执行 所以如果代码能走到这里 说明需要登陆
  const tokenObj = getToken()
  // console.log('tokenObj', tokenObj)
  // 打印出来 没有token 是null 去登陆页面 (登陆完成后 才能打印出token)
  // 要用全等去做判断
  if (tokenObj === null) {
    Toast.fail('请先登陆')
    //  url携带back参数, 记录之前访问的地址(页面) 目的是在url中携带我们本来希望访问的路由地址
    // 这样在登录成功之后 就可以根据这个值 决定页面的跳转哈 back是自定义的
    return next({ path: '/login', query: { back: to.path } })
  }
  // 6月26号--------------------6月26号-------------
  if (store.state.cangkuuserInfo.name) {
    // (注意判断条件,不能是空对象)
    return next() // 判断本地仓库是否有用户信息, 如果有就直接通过,这样在控制台的NetWork里面就不会多次的去调用接口
  }
  // 上面得tokenObj === null 只要token不为空, 就先放走 (注意但是token的对错是不知道的,所以必须判断对错)
  // 前端是无法判断token对错的,因为token加密算法没有放在前端
  // 后端会给一些需要token的接口,能调成功说明token没问题(如果调不成功说明token是有错的)
  getUserInfo()
    // getUserInfo是api/my.js 获取用户信息的
    // 如果能代码能进到.then,说明用户的数据是没有问题的,token也是没有问题的(那就把他放走next())
    .then(res => {
      // console.log('res', res)
      // 注意 这里是路由 用this是拿不到的
      // console.log(this.$store.state.msg)
      // 通回过vuex保存数据 (res.data.data就是获取到用户登陆后的数据 然后将这数据传递给仓库保存起来)
      store.commit('setUserInfo', res.data.data)
      next()
    })
    // 如果进到了.catch,说明用户数据有问题(接口调用有问题)那么token就是错误的
    .catch(errRes => {
      // 这种方式可以打印出来对象的结构(就是控制台里面对象的数据)----新方法打印数据
      // console.dir(errRes)
      // console.dir(errRes.response.status)    // 打印得401  response是响应的意思
      // 401状态码的判断,是为了让逻辑更加的严谨 401是没登陆, 或者用户的token有问题
      if (errRes.response.status === 401) {
        // 说明token有问题 那就删除有问题的token
        removeToken()
        Toast('请先登陆')
        // 去到登陆页面   url携带back参数, 记录之前访问的地址
        next({ path: '/login', query: { back: to.path } })
      }
    })
})

// 导出 让外部导入并使用
// 这里导出的 router 有manin.js  import router from './router' 导入了
// 所有可以把其他子组件的path 路径写在这个index.js里面
export default router

// 6月23号----------------------------6月23号----------
// 实例化路由对象之后 才会执行的函数
// 注册导航守卫 (全局前置守卫  跳转之前执行)
// 导航守卫是什么? 可以理解为是一个`警察` 一个回调函数 导航守卫有多个 （有个必须执行的函数 next（））
// router.beforeEach((to, from, next) => {
//   // to 去到什么地方 的路由信息 this.$route获取到的是一致的
// (比如我在my然后去到login 这是打印的就是login)
//   console.log('to:', to)
//   // from 从哪里来的 路由信息 this.$route获取到的是一致的
// 打印的是my 从my页面过来的
//   console.log('from:', from)
//   // console.log('next:', next)
//   // 不执行next 卡在这个地方 路由的就 不能切换到另外一个地址
// 不执行就是能通过网址 进入其他页面
//   // 必须执行的函数
//   next()
// })
